/*
 * start.cc
 *
 *  Created on: 13.02.2011
 *      Author: SVaroG, jkallup, diogenes
 *    Function: Three-Pass Compiler/Interpreter
 */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <malloc.h>
#include <unistd.h>
#include <sys/types.h>

#include <string>
#include <sstream>
#include <iostream>
#include <locale>
#include <list>
#include <stack>
using namespace std;

#undef strlwr

#define TOK_NUMBER 200
#define TOK_ID 201
#define TOK_FILE 202
#define TOK_IF 203
#define TOK_ELSE 204
#define TOK_ENDIF 205
#define TOK_PRINT 206
#define _LBR_ 207
#define _RBR_ 208
#define TOK_FUNCTION 209
#define TOK_RETURN 210

#define TOK_MOVV 400
#define TOK_PUSH 401
#define TOK_CMP 403
#define TOK_JMP 404
#define TOK_CALL 405
#define TOK_STOREV 406
#define TOK_OUT 407
#define TOK_TEXT 408
#define TOK_PAUSE 409
#define TOK_CLRSCR 410

#define TOK_ADD 1405
#define TOK_SUB 1406
#define TOK_MUL 1407
#define TOK_DIV 1408

#define TT_EXPR 100
#define TT_STRING 101
#define TT_FUNC 102
#define TT_IDENT 103

FILE *finput;
int lineno = 1;
int tokentype = 0;
int print_parameters;
char token_buffer[2048];
char numvalstr[256];
double numval;

int passmode;
struct keywords
{
	int mode;
	char* token;
	int id;
} keyword[] = {
	// -------------------------
	// One-Pass instructions ...
	// -------------------------
	{ 0, (char*) "if", TOK_IF},
	{ 0, (char*) "else", TOK_ELSE},
	{ 0, (char*) "endif", TOK_ENDIF},
	{ 0, (char*) "file", TOK_FILE},
	{ 0, (char*) "pause", TOK_PAUSE},
	{ 0, (char*) "clrscr", TOK_CLRSCR},
	{ 0, (char*) "function", TOK_FUNCTION},
	{ 0, (char*) "return", TOK_RETURN},

	// -------------------------
	// Two-Pass instructions ...
	// -------------------------
	{ 1, (char*) "movv", TOK_MOVV},
	{ 1, (char*) "add", TOK_ADD},
	{ 1, (char*) "sub", TOK_SUB},
	{ 1, (char*) "mul", TOK_MUL},
	{ 1, (char*) "div", TOK_DIV},
	{ 1, (char*) "push", TOK_PUSH},
	{ 1, (char*) "print", TOK_PRINT},
	{ 1, (char*) "cmp", TOK_CMP},
	{ 1, (char*) "jmp", TOK_JMP},
	{ 1, (char*) "call", TOK_CALL},
	{ 1, (char*) "storev", TOK_STOREV},
	{ 1, (char*) "out", TOK_OUT},
	{ 1, (char*) "text", TOK_TEXT},
	{ 0, 0,0 }
};

// -----------------------------------
// stack structure for saved variables
// -----------------------------------
enum TTtype { ttUnknown, ttExpr, ttString };
typedef struct variables_struct
{
	TTtype type;
	double val;
	int ret_address;
	std::string name;
	std::string str;
} variables;

stack<variables> var_item;		// variables
stack<variables> print_item;	// print "text" ...
stack<variables> call_return;	// caller return address

class Parser
{
private:
	stringstream memstream;

	int skip_white_space();
	int else_label;
	double FCurrentStackValue;

	void error(char *msg);
	int lex(void);
	void match(int t);
	void handle_if(void);
	char *handle_string(void);
	void handle_print(void);
	void handle_output(void);
	void handle_numexpr(void);
	void handle_push(void);
	void handle_add(void);
	void handle_sub(void);
	void handle_mul(void);
	void handle_div(void);
	void handle_cmp(void);
	void term();
	void factor();
	void exec_print(void);
	void parse_numexpr(void);
	void handle_function(void);
	void handle_parameters(string fname);
	void handle_func_call(string buffer);
	void handle_storev(void);
	int lookahead;
public:
	Parser(void);
	void et(void);
	void stmt(int mode);
	void setText(char *txt);
	char* getText(void);
};

class Parser *parse = NULL;

//! Constructor
Parser::Parser(void)
{
	FCurrentStackValue = 0.00;
	else_label = 0;
}
//! Set Text
//! \param txt a text
void  Parser::setText(char *txt) { memstream.write(txt,strlen(txt)); }
//! Get Text
//! \return a pointer to a text
char* Parser::getText(void)  {	return (char*)memstream.str().c_str(); }

struct funcparameters {
	string f_name;		// function name
	string p_name;		// parameter name
	int p_type;			// parameter type
	double p_expr;		// double value of actual parameter
	string  p_str;		// string value of .".
};

struct listelement {
	int a_type;
	int f_loc;
    char *val_name;
	char *val_str;
	double val_expr;
    listelement *next;
    //funcparameters *parameters;
};

struct locationelement {
	int loc;
	string name;
	locationelement *next;
};

list<funcparameters> funcParameter;
listelement   *varList = NULL;
locationelement *locListe = NULL;

//! insert var list
//! \param lname
//! \param val
void insert_varList(string lname, double val)
{
	listelement *ptr = new listelement;
	ptr->val_name = new char[lname.size()+1];
	strcpy(ptr->val_name,(char*)lname.c_str());
	ptr->a_type = TT_EXPR;
	ptr->val_expr = val;
	ptr->next = varList;
	varList  = ptr;
}
//! insert fuctions list
//! \param lname
//! \param loc
void insert_funcList(string lname, int loc)
{
	listelement *ptr = new listelement;
	ptr->val_name = new char[lname.size()+1];
	strcpy(ptr->val_name,(char*)lname.c_str());
	ptr->a_type = TT_FUNC;
	ptr->f_loc = loc;
	ptr->next = varList;
	varList  = ptr;
}
//! find a list element
//! \param lname
//! \return a pointer to list element function
//! \sa listelement
struct listelement* find(string lname)
{
	listelement *ptr = new listelement;
	ptr = varList;
	try
	{
	while (ptr)
	{
		//cout << "|" << ptr->val_name << "| ";
		if (!ptr->next) break;
		if (!strlen(ptr->val_name)) break;
		if (!strcmp(ptr->val_name,lname.c_str()))
			return ptr;

		ptr = ptr->next;
	}
	} catch (...) {
		printf("ssssss");
	}
	return NULL;
}
//! Insert Location
//! \param lname
//! \param pos
void insertLocation(string lname, int pos)
{
	locationelement *ptr = new locationelement;
	ptr->name = lname;
	ptr->loc  = pos;
	ptr->next = locListe;
	locListe  = ptr;
}
//! Out Location
//! \param lname
//! \return 
int outLocation(string lname)
{
	while (locListe)
	{
		if (locListe->name.size() <= 0) return -1;
		if (locListe->name == lname) return locListe->loc;

		locListe = locListe->next;
	}

	return -1;
}

string strlower(string s)
{
	locale loc;
	stringstream str;
	for (size_t i=0; i<s.length(); ++i)
		str << tolower(s[i],loc);
	return str.str();
}

//! Slip white space
//! \return 
int Parser::skip_white_space (void)
{
  int c;
  int inside;

  c = getc (finput);

  for (;;)
    {
      int cplus_comment;

      switch (c)
	  {
	    case '/':
	  /* FIXME: Should probably be merged with copy_comment.  */
	  c = getc (finput);
	  if (c != '*' && c != '/')
	    {
	      cout << "unexpected `/' found and ignored" << endl;
	      break;
	    }
	  cplus_comment = (c == '/');

	  c = getc (finput);

	  inside = 1;
	  while (inside)
	    {
	      if (!cplus_comment && c == '*')
		{
		  while (c == '*')
		    c = getc (finput);

		  if (c == '/')
		    {
		      inside = 0;
		      c = getc (finput);
		    }
		}
	      else if (c == '\n')
		{
		  lineno++;
		  if (cplus_comment)
		    inside = 0;
		  c = getc (finput);
		}
	      else if (c == EOF)
		  {
			cout << "unterminated comment" << endl;
			exit(1);
		  }
	      else
		c = getc (finput);
	    }

	  break;

	case '\n':
	  lineno++;

	case ' ':
	case '\t':
	case '\f':
	  c = getc (finput);
	  break;

	default:
	  return c;
	}
  }
}

// lex
// \return
int Parser::lex(void)
{
	int c;
	c = skip_white_space();

	switch (c)
	{
		case EOF:
		return EOF;

		case 'A':    case 'B':    case 'C':    case 'D':    case 'E':
		case 'F':    case 'G':    case 'H':    case 'I':    case 'J':
		case 'K':    case 'L':    case 'M':    case 'N':    case 'O':
		case 'P':    case 'Q':    case 'R':    case 'S':    case 'T':
		case 'U':    case 'V':    case 'W':    case 'X':    case 'Y':
		case 'Z':
		case 'a':    case 'b':    case 'c':    case 'd':    case 'e':
		case 'f':    case 'g':    case 'h':    case 'i':    case 'j':
		case 'k':    case 'l':    case 'm':    case 'n':    case 'o':
		case 'p':    case 'q':    case 'r':    case 's':    case 't':
		case 'u':    case 'v':    case 'w':    case 'x':    case 'y':
		case 'z':
	    case '_':

		strcpy(token_buffer,"");

		while (isalnum (c) || c == '_' || c == '.')
		{
			char buffer[5];
			sprintf(buffer,"%c",c);
			strcat(token_buffer,buffer);
			c = getc(finput);
		}	ungetc(c,finput);

		for (int i = 0; keyword[i].id != 0; i++)
		{
			if (strlower(token_buffer) == strlower(keyword[i].token))
			return keyword[i].id;
		}

		return TOK_ID;

		break;

		case '?':
			return TOK_PRINT;
		break;

		case '0':    case '1':    case '2':    case '3':    case '4':
		case '5':    case '6':    case '7':    case '8':    case '9':
		case '.':
		{
			strcpy(numvalstr,"");

			while (isdigit (c) || c == '.')
			{
				char buffer[5];
				sprintf(buffer,"%c",c);
				strcat(numvalstr,buffer);
				c = getc(finput);
			}   ungetc(c,finput);

			numval = atof(numvalstr);
			return TOK_NUMBER;
		}
		break;

		case '\"': return '\"';
		break;
	}
	return c;
}

//! Handle push
//! \note second pass function to handle pushes onto the stack ...
void Parser::handle_push(void)
{
	variables var;
	int c;

	c = lex();
	if (c == TOK_NUMBER)
	{
		var.type = ttExpr;
		var.val = numval;
		var_item.push(var);
	}
	else if (c == TOK_ID)
	{
		for(list<funcparameters>::const_iterator it = funcParameter.begin(); it != funcParameter.end(); ++it)
		{
			if (it->p_name == token_buffer)
			{
				if (it->p_type == TT_EXPR)		var.type = ttExpr; else
				if (it->p_type == TT_STRING)	var.type = ttString;

				var.name = it->p_name;
				var.val  = it->p_expr;
				var.str  = it->p_str;
				var_item.push(var);

				return;
			}
		}
	}
}
//! Handle add
void Parser::handle_add(void)
{
	variables var1, var2,  var;

	var1 = var_item.top(); var_item.pop();
	var2 = var_item.top(); var_item.pop();

	var.type = ttExpr;
	var.val = var1.val + var2.val;

	FCurrentStackValue = var.val;
	var_item.push(var);
}
//! Handle sub
void Parser::handle_sub(void)
{
	variables var1, var2,  var;

	var1 = var_item.top(); var_item.pop();
	var2 = var_item.top(); var_item.pop();

	var.type = ttExpr;
	var.val = var2.val - var1.val;

	FCurrentStackValue = var.val;
	var_item.push(var);
}
//! Handle mul
void Parser::handle_mul(void)
{
	variables var1, var2,  var;

	var1 = var_item.top(); var_item.pop();
	var2 = var_item.top(); var_item.pop();

	var.type = ttExpr;
	var.val = var1.val * var2.val;

	FCurrentStackValue = var.val;
	var_item.push(var);
}
//! Handle div
void Parser::handle_div(void)
{
	if (passmode == 3)
	{
		variables var1, var2,  var;

		var1 = var_item.top(); var_item.pop();
		var2 = var_item.top(); var_item.pop();

		var.type = ttExpr;
		var.val = var1.val / var2.val;

		FCurrentStackValue = var.val;
		var_item.push(var);
	}
}

// -----------------------------------------------------------
//! match
// \param t
void Parser::match(int t)
{
	if (lookahead == t) {
		lookahead = lex();
	}
	else error((char*)"Syntaxfehler.");
}
//! factor
void Parser::factor(void)
{
	if (lookahead == '(')
	{
		match('(');
		handle_numexpr();
		match(')');
	}
	else if (lookahead == TOK_NUMBER)
	{
		if (passmode == 1)
		memstream << "\tpush " << (double) numval << endl;
		match(TOK_NUMBER);
	}
	else if (lookahead == TOK_ID)
	{
		if (passmode == 1)
		memstream << "\tpush " << token_buffer << endl;
		match(TOK_ID);
	}
}
//! term
void Parser::term(void)
{
	char t;
	factor();
	while (1)
		switch (lookahead)
		{
			case '*':
			case '/':
				t = lookahead;
				match(lookahead);
				factor();

				if (passmode == 1)
				memstream << (t == '*'?"\tmul":"\tdiv") << endl;
				continue;
			break;
			default: return;
		}
}
//! parse num expr
void Parser::parse_numexpr(void)
{
	lookahead = lex();
	while (lookahead != ';')
	{
		handle_numexpr();
		//match(';');
	}
}
//! handle num expr
void Parser::handle_numexpr(void)
{
	char t;
	term();
	while (1)
		switch (lookahead)
		{
			case '+':
			case '-':
				t = lookahead;
				match(lookahead);
				term();

				if (passmode == 1)
				memstream << (t == '+'?"\tadd":"\tsub") << endl;
				continue;

			default: return;
		}
}

//! habdle parameter
//! \note handles parameters for function calls
void Parser::handle_parameters(string fname)
{
	int c = lex();
	if (c == TOK_ID)
	{
		//cout << token_buffer << endl;

		funcparameters p = { fname, token_buffer, TT_IDENT, 0, token_buffer };
		//strcpy(p.p_name,token_buffer);
		//p.p_str = token_buffer;
		funcParameter.push_back(p);
	}
	/*
	else if (c == TOK_NUMBER)
	{
		funcparameters p = { fname, TT_EXPR, numval, "" };
		funcParameter.push_back(p);

		cout << numval << endl;
	}*/

	c = skip_white_space();
	if (c == ')')
	{
		/*
		for(list<funcparameters>::const_iterator it = funcParameter.begin(); it != funcParameter.end(); ++it)
		{
			cout << it->f_name << ": " << it->p_expr << ", " << it->p_str << endl;
		}*/

		return;
	}
	else if (c == ',') handle_parameters(fname);
	else error((char*)"unzulässige Parameterangabe(n)");
}
//! handle function
void Parser::handle_function(void)
{
	int c = lex();
	if (c == TOK_ID)
	{
		if (passmode == 0)
		{
			c = skip_white_space();
			if (c == '(')
			{
				handle_parameters(token_buffer);
			}
			else ungetc(c, finput);
		}
		if (passmode == 1)
		{
			memstream << (char*)"\treturn"
					  << endl << "function " << token_buffer /*<< (char*)":" */ << endl;
		}

		if (passmode == 2)
		{
			listelement *ptr = new listelement;
			insert_funcList(token_buffer,ftell(finput));
			ptr = find(token_buffer);
			ptr->f_loc = ftell(finput);

			//cout << "--->>>" << ptr->f_loc << endl;
		}
	}
}
//! handle storev
void Parser::handle_storev(void)
{
	int c = lex();
	if (c == TOK_ID)
	{
		if (passmode == 3)
		{
			struct listelement *ptr = new listelement;
			ptr = varList;
			if (!(ptr = find(token_buffer)))
			{
				cout << "list empty" << endl;
				exit(-2);
			}

			ptr->val_expr = FCurrentStackValue;
		}
	}
}

//! handle output
//! \note "out text" stack for text output on screen ...
void Parser::handle_output(void)
{
	int c;
	c = lex(); if (c == TOK_TEXT) {
	c = lex(); if (c == TOK_NUMBER)
	{
		print_parameters = (int)numval;
		if (passmode == 3)
		{
			if (print_item.empty() == true)
			{
				cout << "enmptY" << endl;
				return;
			}
			variables ptr;
			for (c = 0; c < print_parameters+1; c++)
			{
				if (print_item.empty() == true) break;
				print_item.pop();
				ptr = print_item.top();
				cout << ptr.str;

				if (print_item.empty() == true) break;	print_item.pop();
				if (print_item.empty() == true) break;
			}
		}
		print_parameters = 0;
	}
	}
}
//! et
void Parser::et(void)
{
	variables var;
	var = var_item.top();
	cout << "= ";
	cout << var.val;
}
//! hanfle function call
//! \param buffer a string buffer
void Parser::handle_func_call(string buffer)
{
	//string tmp_buffer = buffer;
	if (lookahead == '(')
	{
		if (passmode == 0)
		{
			insert_funcList(buffer,-1);
		}
		else if (passmode == 1)
		{
			//varListe = find(buffer);
			memstream << (char*)"\tcall 0 " << buffer
					  << endl;

			while (1)
			{
				int c = lex();
				if (c == TOK_NUMBER)
				{
					for (list<funcparameters>::iterator it = funcParameter.begin();
						it != funcParameter.end();
						++it) {
						if ((it->f_name == buffer))
						{
							it->f_name = "@" + buffer;
							it->p_type = TT_EXPR;
							it->p_expr = numval;
							it->p_str  = "";
							break;
						}
					}
				}
				else if (c == TOK_ID)
				{
					listelement *ptr = find(token_buffer);
					if (ptr->a_type == TT_EXPR)
					{
						//funcparameters p = { buffer, TT_EXPR, ptr->val_expr, "" };
						//funcParameter.push_front(p);
					}
					else if (ptr->a_type == TT_STRING)
					{
						//funcparameters p = { buffer, TT_STRING, 0, ptr->val_name };
						//funcParameter.push_front(p);
					}
				}

				lookahead = skip_white_space();
				if (lookahead == ')')
				{
					/*
					for(list<funcparameters>::iterator it = funcParameter.begin(); it != funcParameter.end(); ++it)
					{
						cout << it->f_name << "|: " << it->p_name << " :|  " << it->p_expr << ", " << it->p_str << endl;
					}*/

					break;
				}
				else if (lookahead == ',') continue;
				else {
					ungetc(lookahead,finput);
					break;
				}
			}
		}
	}
}

void Parser::handle_cmp(void)
{
	int c = lex();
	if (c == TOK_ID)
	{
		variables var1, var2,  var;

		var1 = var_item.top(); var_item.pop();
		var2 = var_item.top(); var_item.pop();

		if (var2.val != var1.val)
		{
			ostringstream str;
			//str << token_buffer << ":";

			int loc = outLocation(str.str());
			//cout << str.str() << ": " << loc << endl;
			fseek(finput,loc,SEEK_SET);
		}
	}
}

//! stmt
//! \param mode
void Parser::stmt(int mode)
{
	int c;
	while (1)
	{
		c = lex();
		if (c == EOF) break;

		// ---------------
		// second-pass ...
		// ---------------
		else if (c == TOK_PUSH)	handle_push();

		else if (c == TOK_ADD)	{ handle_add(); }
		else if (c == TOK_SUB)	{ handle_sub(); }
		else if (c == TOK_MUL)	{ handle_mul(); }
		else if (c == TOK_DIV)	{ handle_div(); }

		else if (c == TOK_STOREV) handle_storev();
		else if (c == TOK_RETURN)
		{
			if (passmode == 1)
			memstream << "\treturn" << endl;
			else if (passmode == 3)  return;
		}
		else if (c == TOK_OUT)  { handle_output();	}
		else if (c == TOK_CMP) {
			handle_cmp();
		}
		else if (c == TOK_CLRSCR)
		{
			if (passmode == 1)
			{
				memstream << (char*)"\tclrscr" << endl;
			}
			else if (passmode == 3)
			{
				system("cls");
			}
		}
		else if (c == TOK_PAUSE)
		{
			if (passmode == 1)
			{
				memstream << (char*)"\tpause" << endl;
			}
			else if (passmode == 3)
			{
				system("pause");
			}
		}
		else if (c == TOK_CALL)
		{
			if (passmode >= 1)
			{
				c = lex(); // parameter no.
				c = lex(); // function name

				int opos = ftell(finput);
				listelement *ptr = find(token_buffer);

				//cout << "1: " << opos << " 2: " << ptr->f_loc << endl;
				fseek(finput,ptr->f_loc,SEEK_SET);
				stmt(passmode);
				fseek(finput,opos,SEEK_SET);
			}
		}

		// --------------
		// First-Pass ...
		// --------------
		else if (c == TOK_FUNCTION)
		{
			handle_function();
		}
		else if (c == TOK_ELSE)
		{
			if (passmode == 1)
			{
				memstream << "\tjmp L_jmp" << --else_label << endl;
			}
			return;
		}
		else if (c == TOK_IF)
		{
			handle_if();
		}
		else if (c == TOK_ENDIF)
		{
			if (passmode == 1)
			{
				ostringstream z1,z2;
				string s1, s2;

				z1 << (char*)"lc_jmp"
				   << else_label-1
				   << ":";
				s1 =  z1.str();

				z2 << "lc_jmp"
				   << else_label-1;
				s2 =  z2.str();

				memstream << s1;

				insertLocation(s1,memstream.tellp());
				//cout << "------: " << s1 << " - " << memstream.tellp() << "  " << endl;
			}

			print_parameters = 0;
			stmt(mode);
			return;
		}
		else if (c == TOK_ID)
		{
			string s = token_buffer;
			lookahead = skip_white_space();
			if (lookahead == '=')
			{
				parse_numexpr();

				if (passmode == 0)
				{
					insert_varList(s,0.00);
				}
				else if (passmode == 1)
				{
					memstream << (char*)"\tstorev " << s << endl;
				}
			}
			else if (lookahead == '(')
			{
				handle_func_call(s);
				//if (lookahead != ')') error((char*)"Klammer ')' fehlt.");
			}
		}
		else if (c == TOK_PRINT)
		{
			if (passmode == 0 || passmode == 1)
			handle_print();
			else if (passmode == 3) {
				exec_print();
			}
		}
	}
}
//! handle string
//! \return a pointer to char array
char *Parser::handle_string(void)
{
	char *str = (char*) malloc(2048);
	int c = skip_white_space();
	int pos = 0;
	if (c == '"')
	{
		while (1)
		{
			c = getc(finput);

			if (c == '"') break; else
			if (c == '\\') {
				c = getc(finput);
				if (passmode == 3)
				{
					if (c == 'n') str[pos++] = '\n'; else
					if (c == 't') str[pos++] = '\t'; else
					if (c == 'f') str[pos++] = '\f';
				} else {
					str[pos++] = '\\';
					str[pos++] = c;
				}
			} else
			str[pos++] = c;
		}	str[pos] = '\0';

		++print_parameters;
		if (passmode == 3)
		{
			variables ptr;
			ptr.str = str;
			ptr.type = ttString;
			print_item.push(ptr);
		}
	}
	else if (lookahead >= 'a' && lookahead <= 'z')
	{
		ungetc(lookahead,finput);
		c = lex();
		if (c == TOK_FUNCTION)
		{
			cout << "---2-2---";
			handle_function();
		}
		if (c == TOK_ID)
		{

			lookahead = skip_white_space();
			if (lookahead == '(')
			{
				cout << "-->" << token_buffer;
				handle_func_call(token_buffer);
				c = skip_white_space();
				if (c != ')') error((char*)"Klammer ')' fehlt.");
			}
			else ungetc(c,finput);

			struct listelement *ptr = new listelement;
			ptr = varList;
			if (!(ptr = find(token_buffer)))
				error((char*)"Symbol nicht gefunden.");

			cout << ptr->a_type;
			if (ptr->a_type == TT_EXPR)
			{
				char buffer[200];
				sprintf(buffer,"%f",ptr->val_expr);
				strcat(str,buffer);
				cout << buffer;
			}
			else if (ptr->a_type == TT_STRING)
			strcat(str,ptr->val_str);
		}
	}

	c = skip_white_space();
	if (c == '+')
	{
		c = skip_white_space();

		if (c == EOF) error((char*)"EOF erreicht.");
		else if (c == '"')
		{
			ungetc(c,finput);
			string s = handle_string();

			if (passmode == 1)
			memstream << "\tprint \"" << s << "\"" << endl;
		}
	}
	else ungetc(c,finput);

		/*
			c = lex();

			if (c == TOK_FUNCTION)
			{
				handle_function();
			}
			if (c == TOK_ID)
			{
				char cs[256];
				if ((varListe = find(token_buffer)) == NULL)
				{
					cout << "list empty" << endl;
					exit(2);
				}

				if (varListe->a_type == TT_EXPR)
				{
					sprintf(cs,"%f",varListe->val_expr);
					strcat(str,cs);
				}
			}
		}
	}
	else ungetc(c,finput); */
	return (char*)str;
}
//! error
//! \param msg
void Parser::error(char *msg)
{
	printf("Zeile: %d: %s\n",lineno,msg);
	exit(1);
}
//! exec print
void Parser::exec_print(void)
{
	string str;
	lookahead = skip_white_space();
	if (lookahead == '"')
	{
		ungetc(lookahead,finput);
		str = handle_string();

		variables ptr;
		ptr.str = str;
		ptr.type = ttString;
		print_item.push(ptr);
	}
}
//! handle print
void Parser::handle_print(void)
{
	int c;
	c = skip_white_space();
	if (c == '"')
	{
		ungetc(c,finput);
		string str = handle_string();

		//cout << str << endl;

		if (passmode == 1)
		{
			memstream << "\tprint \"" << str << "\"" << endl;
			memstream << "\tout text " << print_parameters << endl;
			print_parameters = 0;
		}
	}
}
//! handle if
void Parser::handle_if(void)
{
	char *str = new char[255];
	int c,out;

	c = lex();
	if (c == TOK_ID)
	{
		//cout << token_buffer << "  <- parameter" << endl;

		//if (passmode == 1)
		{
			for (list<funcparameters>::iterator it = funcParameter.begin();
				it != funcParameter.end();
				++it) {
				//cout << it->p_name << " + " << token_buffer << endl;
				if (it->p_name == token_buffer)
				{
					if (passmode == 1)
					memstream << "\tpush " << token_buffer << endl;
					goto next;
				}
			}
		}

		listelement *ptr = new listelement;
		ptr = varList;

		try
		{
			if ((ptr = find(token_buffer)) == NULL)
			{
				cout << "list empty" << endl;
				exit(2);
			}
		}
		catch (...)
		{
			printf("fehler");
		}

		if (passmode == 1)
		memstream << "\tpush " << ptr->val_name << endl;

	} else if (c == TOK_NUMBER)	{
		sprintf(str,"\tpushv %f\n",numval);
		memstream.write(str,strlen(str));
	}

	next:
	c = skip_white_space();
	if (c == '=')
	{
		c = lex();
		if (c == TOK_NUMBER) {
			if (passmode == 1)
			memstream << "push " << numval << endl;
		} else
		if (c == TOK_ID) {
			cout << "ssssssssssssssssssssss" << endl;
			if ((varList = find(token_buffer)) == NULL)
			{
				cout << "list empty" << endl;
				exit(2);
			}

			cout << "eeeeeeeeeeeeeeeeeeeee333333333" << endl;
			if (passmode == 1)
			memstream << "pushvi " << varList->val_name << endl;
		}

		if (passmode == 1)
		{
			sprintf(str,"\tcmp LC_jmp%d\n",else_label);
			memstream.write(str,strlen(str));
		}

		out = else_label++;
		print_parameters = 0;
		stmt(passmode);

		/*
		if (passmode == 1)
		{
			sprintf(str,"LC_jmp%d:\n",out);
			memstream.write(str,strlen(str));

			insertLocation(str,memstream.tellp());

			cout << "-------------------------" << endl;
		}*/
	} else
		cout << "\tcmp neq" << endl;

	delete str;
}

int main(int argc, char **argv)
{
		varList  = new listelement;
		locListe = new locationelement;

		parse = new Parser;

		if ((finput = fopen(argv[1],"r")) == NULL)
		{
			cout << "can't open input file\n";
			return -2;
		}

		print_parameters = 0;
		fseek(finput,0,SEEK_SET);
		lineno   = 1;
		passmode = 0; // scan
		parse->stmt(passmode);

		print_parameters = 0;
		fseek(finput,0,SEEK_SET);
		lineno   = 1;
		passmode = 1; // parse
		parse->stmt(passmode);

		fclose(finput);

		char buffer[2048];
		sprintf(buffer,"%s.asm",argv[1]);
		if ((finput = fopen(buffer,"w")) == NULL)
		{
			cout << "can't open output file" << endl;
			return -2;
		}

		//cout << parse->getText();
		fwrite(parse->getText(),1,
		strlen(parse->getText()) ,finput);

		fclose(finput);

		if ((finput = fopen(buffer,"r")) == NULL)
		{
			cout << "can't open input file" << endl;
			return -2;
		}

		print_parameters = 0;
		fseek(finput,0,SEEK_SET);
		lineno   = 1;
		passmode = 2;
		parse->stmt(passmode);

		print_parameters = 0;
		fseek(finput,0,SEEK_SET);
		lineno   = 1;
		passmode = 3;
		parse->stmt(passmode);

		//cout << outLocation("L_jmp1:\n") << endl;
		fclose(finput);

		delete parse;

		delete locListe;
		delete varList;
}
